import { useState, useCallback, useRef, useEffect } from 'react';
import type { Room, RoomAvailability } from '../../../types/room';
import { RoomStatus } from '../../../types/room';

// 拖拽状态枚举
export const DragState = {
  IDLE: 'idle', // 空闲状态
  DRAGGING: 'dragging', // 拖拽中
  HOVERING: 'hovering', // 悬停在目标上
} as const;

export type DragState = (typeof DragState)[keyof typeof DragState];

// 拖拽数据接口
export interface DragData {
  sourceRoom: Room;
  sourceDate: string;
  sourceStatus: RoomStatus;
  startX: number;
  startY: number;
  currentX: number;
  currentY: number;
  offset: { x: number; y: number };
}

// 拖拽目标接口
export interface DropTarget {
  room: Room;
  date: string;
  isValid: boolean;
  reason?: string;
}

// 拖拽状态接口
export interface DragDropState {
  state: DragState;
  dragData: DragData | null;
  dropTarget: DropTarget | null;
  isDragging: boolean;
  canDrop: boolean;
}

interface UseDragDropReturn {
  dragState: DragDropState;
  startDrag: (
    event: React.MouseEvent,
    room: Room,
    date: string,
    status: RoomStatus,
    cellBounds: { x: number; y: number; width: number; height: number }
  ) => void;
  updateDrag: (event: React.MouseEvent) => void;
  endDrag: () => void;
  cancelDrag: () => void;
  validateDrop: (targetRoom: Room, targetDate: string) => boolean;
  renderDragPreview: (ctx: CanvasRenderingContext2D) => void;
}

export const useDragDrop = (
  rooms: Room[],
  dates: string[],
  availabilities: RoomAvailability[],
  config: any,
  onDrop?: (
    sourceRoom: Room,
    sourceDate: string,
    targetRoom: Room,
    targetDate: string
  ) => void
): UseDragDropReturn => {
  const [dragState, setDragState] = useState<DragDropState>({
    state: DragState.IDLE,
    dragData: null,
    dropTarget: null,
    isDragging: false,
    canDrop: false,
  });

  const dragThreshold = 5; // 拖拽阈值（像素）
  const animationFrameRef = useRef<number | null>(null);

  // 开始拖拽
  const startDrag = useCallback(
    (
      event: React.MouseEvent,
      room: Room,
      date: string,
      status: RoomStatus,
      cellBounds: { x: number; y: number; width: number; height: number }
    ) => {
      // 只有已预订的房间才能拖拽
      if (
        status !== 'booked' &&
        status !== 'occupied' &&
        status !== 'partially_booked'
      ) {
        console.log('只有已预订的房间才能拖拽');
        return;
      }

      event.preventDefault();
      event.stopPropagation();

      const startX = event.clientX;
      const startY = event.clientY;

      // 计算鼠标相对于单元格的偏移
      const offset = {
        x: startX - cellBounds.x,
        y: startY - cellBounds.y,
      };

      const dragData: DragData = {
        sourceRoom: room,
        sourceDate: date,
        sourceStatus: status,
        startX,
        startY,
        currentX: startX,
        currentY: startY,
        offset,
      };

      setDragState({
        state: DragState.DRAGGING,
        dragData,
        dropTarget: null,
        isDragging: true,
        canDrop: false,
      });

      console.log('开始拖拽:', {
        房间: room.roomNumber,
        日期: date,
        状态: status,
        起始位置: { x: startX, y: startY },
      });
    },
    []
  );

  // 更新拖拽位置
  const updateDrag = useCallback(
    (event: React.MouseEvent) => {
      if (!dragState.isDragging || !dragState.dragData) return;

      const currentX = event.clientX;
      const currentY = event.clientY;

      // 检查是否超过拖拽阈值
      const deltaX = Math.abs(currentX - dragState.dragData.startX);
      const deltaY = Math.abs(currentY - dragState.dragData.startY);

      if (
        deltaX < dragThreshold &&
        deltaY < dragThreshold &&
        dragState.state === DragState.IDLE
      ) {
        return;
      }

      // 计算目标位置
      const rect = (
        event.currentTarget as HTMLCanvasElement
      ).getBoundingClientRect();
      const relativeX = currentX - rect.left;
      const relativeY = currentY - rect.top;

      let dropTarget: DropTarget | null = null;

      // 检查是否在有效的拖拽区域内
      if (relativeX > config.roomTypeWidth + config.roomNumberWidth) {
        const dateIndex = Math.floor(
          (relativeX - config.roomTypeWidth - config.roomNumberWidth) /
            config.cellWidth
        );
        const roomIndex = Math.floor(relativeY / config.cellHeight);

        if (
          dateIndex >= 0 &&
          dateIndex < dates.length &&
          roomIndex >= 0 &&
          roomIndex < rooms.length
        ) {
          const targetRoom = rooms[roomIndex];
          const targetDate = dates[dateIndex];
          const isValid = validateDrop(targetRoom, targetDate);

          dropTarget = {
            room: targetRoom,
            date: targetDate,
            isValid,
            reason: isValid ? undefined : '目标位置已被占用或不可用',
          };
        }
      }

      // 使用 requestAnimationFrame 优化性能
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }

      animationFrameRef.current = requestAnimationFrame(() => {
        setDragState(prev => ({
          ...prev,
          state: dropTarget ? DragState.HOVERING : DragState.DRAGGING,
          dragData: prev.dragData
            ? {
                ...prev.dragData,
                currentX,
                currentY,
              }
            : null,
          dropTarget,
          canDrop: dropTarget?.isValid || false,
        }));
      });
    },
    [
      dragState.isDragging,
      dragState.dragData,
      dragState.state,
      config,
      dates,
      rooms,
    ]
  );

  // 结束拖拽
  const endDrag = useCallback(() => {
    if (!dragState.isDragging || !dragState.dragData) return;

    const { dragData, dropTarget } = dragState;

    // 如果有有效的拖拽目标，执行拖拽操作
    if (dropTarget && dropTarget.isValid && onDrop) {
      console.log('执行拖拽操作:', {
        源房间: dragData.sourceRoom.roomNumber,
        源日期: dragData.sourceDate,
        目标房间: dropTarget.room.roomNumber,
        目标日期: dropTarget.date,
      });

      onDrop(
        dragData.sourceRoom,
        dragData.sourceDate,
        dropTarget.room,
        dropTarget.date
      );
    } else {
      console.log('拖拽取消 - 无效目标或未找到目标');
    }

    // 重置拖拽状态
    setDragState({
      state: DragState.IDLE,
      dragData: null,
      dropTarget: null,
      isDragging: false,
      canDrop: false,
    });
  }, [dragState.isDragging, dragState.dragData, dragState.dropTarget, onDrop]);

  // 取消拖拽
  const cancelDrag = useCallback(() => {
    console.log('拖拽被取消');
    setDragState({
      state: DragState.IDLE,
      dragData: null,
      dropTarget: null,
      isDragging: false,
      canDrop: false,
    });
  }, []);

  // 验证拖拽目标是否有效
  const validateDrop = useCallback(
    (targetRoom: Room, targetDate: string): boolean => {
      if (!dragState.dragData) return false;

      const { sourceRoom, sourceDate } = dragState.dragData;

      // 不能拖拽到相同位置
      if (sourceRoom.id === targetRoom.id && sourceDate === targetDate) {
        return false;
      }

      // 检查目标位置是否已被占用
      const targetAvailability = availabilities.find(
        av => av.roomId === targetRoom.id && av.month === targetDate
      );

      // 如果目标位置有预订，则不允许拖拽
      if (targetAvailability && targetAvailability.status !== 'available') {
        return false;
      }

      // 检查目标房间是否在维护中
      if (targetAvailability?.status === 'maintenance') {
        return false;
      }

      // TODO: 添加更多业务规则验证
      // - 房间类型兼容性
      // - 日期有效性
      // - 用户权限等

      return true;
    },
    [dragState.dragData, availabilities]
  );

  // 渲染拖拽预览
  const renderDragPreview = useCallback(
    (ctx: CanvasRenderingContext2D) => {
      if (!dragState.isDragging || !dragState.dragData) return;

      const { dragData, dropTarget } = dragState;

      // 保存画布状态
      ctx.save();

      // 绘制拖拽中的预览
      const previewWidth = config.cellWidth;
      const previewHeight = config.cellHeight;

      // 计算预览位置（跟随鼠标，但有偏移）
      const rect = ctx.canvas.getBoundingClientRect();
      const previewX = dragData.currentX - rect.left - dragData.offset.x;
      const previewY = dragData.currentY - rect.top - dragData.offset.y;

      // 绘制半透明的预览框
      ctx.globalAlpha = 0.7;
      ctx.fillStyle = dropTarget?.isValid ? '#4caf50' : '#f44336';
      ctx.fillRect(previewX, previewY, previewWidth, previewHeight);

      // 绘制边框
      ctx.globalAlpha = 1;
      ctx.strokeStyle = dropTarget?.isValid ? '#2e7d32' : '#d32f2f';
      ctx.lineWidth = 2;
      ctx.setLineDash([5, 5]);
      ctx.strokeRect(previewX, previewY, previewWidth, previewHeight);
      ctx.setLineDash([]);

      // 绘制房间号
      ctx.fillStyle = '#ffffff';
      ctx.font =
        'bold 12px -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif';
      ctx.textAlign = 'center';
      ctx.textBaseline = 'middle';
      ctx.fillText(
        dragData.sourceRoom.roomNumber,
        previewX + previewWidth / 2,
        previewY + previewHeight / 2
      );

      // 如果有目标位置，绘制目标高亮
      if (dropTarget) {
        const roomIndex = rooms.findIndex(
          room => room.id === dropTarget.room.id
        );
        const dateIndex = dates.indexOf(dropTarget.date);

        if (roomIndex !== -1 && dateIndex !== -1) {
          const targetX =
            config.roomTypeWidth +
            config.roomNumberWidth +
            dateIndex * config.cellWidth;
          const targetY = roomIndex * config.cellHeight;

          // 绘制目标位置高亮
          ctx.globalAlpha = 0.3;
          ctx.fillStyle = dropTarget.isValid ? '#4caf50' : '#f44336';
          ctx.fillRect(targetX, targetY, config.cellWidth, config.cellHeight);

          // 绘制目标边框
          ctx.globalAlpha = 0.8;
          ctx.strokeStyle = dropTarget.isValid ? '#2e7d32' : '#d32f2f';
          ctx.lineWidth = 3;
          ctx.strokeRect(targetX, targetY, config.cellWidth, config.cellHeight);
        }
      }

      // 恢复画布状态
      ctx.restore();
    },
    [
      dragState.isDragging,
      dragState.dragData,
      dragState.dropTarget,
      config,
      rooms,
      dates,
    ]
  );

  // 键盘事件处理（ESC键取消拖拽）
  useEffect(() => {
    const handleKeyDown = (event: KeyboardEvent) => {
      if (event.key === 'Escape' && dragState.isDragging) {
        cancelDrag();
      }
    };

    if (dragState.isDragging) {
      document.addEventListener('keydown', handleKeyDown);
      return () => document.removeEventListener('keydown', handleKeyDown);
    }
  }, [dragState.isDragging, cancelDrag]);

  // 清理动画帧
  useEffect(() => {
    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
    };
  }, []);

  return {
    dragState,
    startDrag,
    updateDrag,
    endDrag,
    cancelDrag,
    validateDrop,
    renderDragPreview,
  };
};
